﻿using System.Collections.Generic;
using System.IO;
using System.Web;
using wojilu.cms.Domain;
using wojilu.Web.Mvc;
using wojilu.Serialization;
using System.Xml;
using System.Text;
using System;
using System.Reflection;
using wojilu.Reflection;
using wojilu.ORM;
using wojilu.DI;
using System.Collections;
using wojilu.Data;
using System.Data;
using System.Data.OleDb;
using System.Diagnostics;

namespace wojilu.cms.Controller.Admin
{
    public enum Operator
    { 
        None,
        SELECT,
        INSERT,
        UPDATE,
        DELETE
    }

    public class JsonController : ControllerBase
    {
        public JsonController()
        {
            HideLayout(typeof(LayoutController));
        }

        private string fTableName = "";
        public void Index()
        {
            fTableName = ctx.route.getItem("tablename");

            if (!ObjectContext.Instance.DynamicTableList.ContainsKey(fTableName))
            {
                GetTableStructure(fTableName);
            }

            StringBuilder[] sbArray = ObjectContext.Instance.DynamicTableList[fTableName];
            string columns = string.Format(DATAGRIDCOLUMNSTEMPLATE, sbArray[0].ToString());

            set("jsonColumns", columns);
            set("jsonAppendRow", sbArray[1].ToString());
            //set("jsonGetURL", to(new JsonController().ListAllNew));
            //set("jsonPostURL", to(new JsonController().Post));
            set("jsonGetURL", getLink("ListAllNew", fTableName));
            set("jsonPostURL", getLink("Post", fTableName));
        }

        public String getLink(String action, String tableName)
        {
            return "/json/" + action + "/" + tableName + MvcConfig.Instance.UrlExt;
        }

        private void GetDataGrid() { }

        private const string CLASSTEMPLATE = "using System;using System.Collections.Generic;using System.Text;using wojilu.ORM; namespace wojilu.cms.Domain {{    public class {0} : ObjectBase<{0}> {{ {1} }} }}";
        private const string PROPERTYTEMPLATE = "  private {1} f{0};  public {1} {0} {{ get{{return f{0};}} set{{f{0} = value;}} }}";
        private const string DATAGRIDCOLUMNSTEMPLATE = "[ {0} ]";
        private const string COLUMNTEMPLATE = "{{ field: '{0}', title: '{0}', width: 120, editor: 'text' }}";
        private const string NEWROWTEMPLATE = "{0}:{1}";

       

        private void GetTableStructure(string tableName)
        {
            String connectionString = DbConfig.GetConnectionString(DbConfig.DefaultDbName);
            OleDbConnection conn = DataFactory.GetConnection(connectionString, DatabaseType.Access) as OleDbConnection;
            StringBuilder sbDGColumns;
            StringBuilder sbProperties;
            StringBuilder sbAppendRow;
            try
            { 
                conn.Open();
                DataTable schemaTable = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables,
                new object[] { null, null, tableName, "TABLE" });
                sbProperties = new StringBuilder();
                sbDGColumns = new StringBuilder();
                sbAppendRow = new StringBuilder();

                foreach (DataRow dr in schemaTable.Rows)
                {
                    //表名 
                    Trace.WriteLine(dr["TABLE_NAME"]);
                    //字段名 
                    DataTable columnTable = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Columns,
                    new object[] { null, null, dr["TABLE_NAME"].ToString(), null });

                    foreach (DataRow dr2 in columnTable.Rows)
                    {
                        string name = dr2["COLUMN_NAME"].ToString();
                        string type = dr2["DATA_TYPE"].ToString();

                        if (!name.ToLower().Equals("id"))
                        {
                            string property = string.Format(PROPERTYTEMPLATE, name, GetType(type));
                            sbProperties.Append(property);
                        }
                        // add column array for datagrid
                        if (sbDGColumns.Length > 0)
                        {
                            sbDGColumns.Append(",");
                        }
                        sbDGColumns.AppendFormat(COLUMNTEMPLATE, name);

                        // add column array for datagrid
                        if (sbAppendRow.Length > 0)
                        {
                            sbAppendRow.Append(",");
                        }
                        sbAppendRow.AppendFormat(NEWROWTEMPLATE, name, "''");
                    }
                }
                // cache the expensive data
                ObjectContext.Instance.DynamicTableList.Add(fTableName, new StringBuilder[] { sbDGColumns, sbAppendRow, sbProperties });
            }
            finally
            {
                conn.Close();
            }
        }

        private string GetType(string type)
        {
            string result = "string";
            switch (type)
            {
                case "System.Byte":
                case "System.SByte":
                case "System.Int32":
                case "System.Int16":
                case "System.Int64":
                case "System.UInt32":
                case "System.UInt16":
                case "System.UInt64":
                case "3":
                    result = "int";
                    break;
                case "System.DateTime":
                    result = "Date";
                    break;
                case "System.TimeSpan":
                case "7":
                    result = "DateTime";
                    break;
                case "System.Double":
                case "System.Single":
                case "System.Decimal":
                    result = "double";
                    break;
                case "System.String":
                case "System.Char":
                    //int length = column.MaxLength;
                    //result = (length == int.MaxValue) ? "text" : "string";
                    break;
                case "System.Byte[]":
                    result = "blob";
                    break;
                default:
                    result = "string";
                    break;
            }
            return result;
         }

        public void ListAllNew()
        {
            fTableName = ctx.route.getItem("tablename");

            if (!MappingClass.Instance.AssemblyList.Contains(fTableName))
            {
                StringBuilder[] sbArray = ObjectContext.Instance.DynamicTableList[fTableName];
                string code = string.Format(CLASSTEMPLATE, fTableName, sbArray[2].ToString());
                //string code = "using System;using System.Collections.Generic;using System.Text;using wojilu.ORM; namespace wojilu.cms.Domain {    public class Test : ObjectBase<Test> {private string fTitle;  [NotNull( \"请输入标题\" ), Column( Length = 10 )]public string Title { get{return fTitle;} set{fTitle = value;} }}}";
                Assembly a = CodeRunner.CompileCodeToDll(code);
                Type[] mytypes = a.GetTypes();
                MappingClass.LoadByDynamic(MappingClass.Instance,fTableName, a);               
            }
            Assembly ass = MappingClass.Instance.AssemblyList[fTableName] as Assembly;
            Type[] types = ass.GetTypes();
            Type t = types[0];

            var request = ctx.web.Context as HttpContext;
            int pageSize = int.Parse(request.Request["rows"]);
            int currentPage = int.Parse(request.Request["page"]);

            IPageList list = ReflectionUtil.CallMethod(t.BaseType, "findPageDataGrid", new object[] { "", pageSize, currentPage, true }) as IPageList;
            IList re = list.Results;

            string jsonStr = JsonString.ConvertList(re);


            string easyuiJson = "{{ \"total\":{0},\"rows\":{1} }}";

            object obj = ReflectionUtil.CallMethod(t.BaseType, "count", null);

            jsonStr = string.Format(easyuiJson, int.Parse(obj.ToString()), jsonStr);

            ctx.RenderJson(jsonStr);
        }

        public void Post()
        {
            var a = ctx.web.Context as HttpContext;
            Stream2StringNew(a.Request.InputStream);
        }

        private string Stream2StringNew(Stream inputStream)
        {
            fTableName = ctx.route.getItem("tablename");
            Assembly ass = MappingClass.Instance.AssemblyList[fTableName] as Assembly;
            Type[] mytypes = ass.GetTypes();
            Type t1 = mytypes[0];
            
            byte[] data = new byte[inputStream.Length];
            inputStream.Position = 0;
            inputStream.Read(data, 0, data.Length);
            string content = Encoding.UTF8.GetString(data);
            Dictionary<string, object> dic = JSON.ToDictionary(content);
            //iterator over three kinds of data
            foreach (KeyValuePair<string, object> item in dic)
            {
                string key = item.Key;

                Operator op = (Operator)Enum.Parse(typeof(Operator), key, true);
                List<object> objs = item.Value as List<object>;
                //iterator over all items
                foreach (object obj in objs)
                {
                    Dictionary<string, object> article = obj as Dictionary<string, object>;
                    Object ar = JSON.setValueToObject(t1, article);
                    switch (op)
                    {
                        case Operator.INSERT:
                            CreateNew(ar);
                            break;
                        case Operator.UPDATE:
                            Update(ar);
                            break;
                        case Operator.DELETE:
                            Delete(ar);
                            break;
                        default:
                            break;
                    }
                }
            }
            return content;
        }

        public void CreateNew(Object a)
        {
            Result result = db.insert(a);
            if (result.HasErrors)
            {
                errors.Join(result);
            }
        }

        //transfer stream object to string
        private string Stream2String(Stream inputStream)
        {
            byte[] data = new byte[inputStream.Length];
            inputStream.Position = 0;
            inputStream.Read(data, 0, data.Length);
            string content = Encoding.UTF8.GetString(data);
            Dictionary<string, object> dic = JSON.ToDictionary(content);
            //iterator over three kinds of data
            foreach (KeyValuePair<string, object> item in dic)
            {
                string key = item.Key;
               
                Operator op = (Operator)Enum.Parse(typeof(Operator), key, true);
                List<object> objs = item.Value as List<object>;
                //iterator over all items
                foreach (object obj in objs)
                {
                    Dictionary<string, object> article = obj as Dictionary<string, object>;
                    Article1 ar = JSON.setValueToObject(typeof(Article1), article) as Article1;
                    switch (op)
                    {
                        case Operator.INSERT:
                            //Create(ar);
                            break;
                        case Operator.UPDATE:
                            //Update(ar);
                            break;
                        case Operator.DELETE:
                            //Delete(ar);
                            break;
                        default:
                            break;
                    }
                }
            }
            return content;
        }

        public void Create(Article1 a)
        {
            Result result = db.insert(a);
            if (result.HasErrors)
            {
                errors.Join(result);
            }
        }

        public void Update(Object a)
        {
            Result result = db.update(a);
            if (result.HasErrors)
            {
                errors.Join(result);               
            }
        }

        public void Delete(Object a)
        {
            db.delete(a);
        }
    }
}
